import * as vscode from "vscode";
import * as fs from "fs";
import * as path from "path";

export interface KeyMapping {
    [key: string]: string;
}

export class KeyReplacer {
    private keyMapping: KeyMapping = {};

    constructor(private mappingFilePath: string) {
        this.loadKeyMapping();
    }

    /**
     * 加载key映射配置
     */
    private loadKeyMapping(): void {
        try {
            if (fs.existsSync(this.mappingFilePath)) {
                const content = fs.readFileSync(this.mappingFilePath, "utf-8");
                this.keyMapping = JSON.parse(content);
                vscode.window.showInformationMessage(
                    `Loaded ${Object.keys(this.keyMapping).length} key mappings`
                );
            } else {
                vscode.window.showWarningMessage(
                    `Mapping file not found: ${this.mappingFilePath}`
                );
            }
        } catch (error) {
            vscode.window.showErrorMessage(
                `Error loading key mapping: ${error}`
            );
        }
    }

    /**
     * 重新加载映射文件
     */
    public reloadMapping(): void {
        this.loadKeyMapping();
    }

    /**
     * 获取映射对象
     */
    public getMapping(): KeyMapping {
        return this.keyMapping;
    }
    /**
     * 保存映射到文件
     */
    public async saveMapping(): Promise<boolean> {
        try {
            // 确保目录存在
            const dir = path.dirname(this.mappingFilePath);
            if (!fs.existsSync(dir)) {
                fs.mkdirSync(dir, { recursive: true });
            }

            // 格式化并保存
            const content = JSON.stringify(this.keyMapping, null, 2);
            fs.writeFileSync(this.mappingFilePath, content, "utf-8");
            return true;
        } catch (error) {
            vscode.window.showErrorMessage(
                `Error saving mapping file: ${error}`
            );
            return false;
        }
    }

    /**
     * 从文件中提取中文键名
     */
    public async extractChineseKeysFromFile(
        document: vscode.TextDocument
    ): Promise<string[]> {
        const chineseKeys: string[] = [];
        const content = document.getText();

        // 匹配 '[中文]' 或 "[中文]" 模式
        const patterns = [/(['"])\[[\u4e00-\u9fff]+\]\1/g];

        for (const pattern of patterns) {
            let match;
            while ((match = pattern.exec(content)) !== null) {
                let chineseKey: string;
                chineseKey = match[0]?.replace(/['"]/g, "");

                // 确保是中文键并去重
                if (
                    chineseKey &&
                    /[\u4e00-\u9fa5]/.test(chineseKey) &&
                    !chineseKeys.includes(chineseKey)
                ) {
                    chineseKeys.push(chineseKey);
                }
            }
        }

        return chineseKeys;
    }

    /**
     * 从工作区中提取所有中文键名
     */
    public async extractChineseKeysFromWorkspace(): Promise<string[]> {
        const config = vscode.workspace.getConfiguration("keyReplacer");
        const fileExtensions: string[] = config.get("fileExtensions", [
            ".ts",
            ".js",
            ".vue",
            ".json",
        ]);

        if (!vscode.workspace.workspaceFolders) {
            vscode.window.showErrorMessage("No workspace folder open");
            return [];
        }

        const workspaceFolder = vscode.workspace.workspaceFolders[0];
        const files = await this.findFiles(workspaceFolder.uri, fileExtensions);

        // 排除映射文件本身
        const mappingFileName = path.basename(this.mappingFilePath);
        const filteredFiles = files.filter((file) => {
            return path.basename(file.fsPath) !== mappingFileName;
        });

        const allChineseKeys: string[] = [];

        for (const file of filteredFiles) {
            try {
                const document = await vscode.workspace.openTextDocument(file);
                const keys = await this.extractChineseKeysFromFile(document);
                if (keys.length > 0) {
                    keys.forEach((key) => {
                        if (!allChineseKeys.includes(key)) {
                            allChineseKeys.push(key);
                        }
                    });
                }
            } catch (error) {
                console.error(`Error processing ${file.fsPath}:`, error);
            }
        }

        return allChineseKeys;
    }

    /**
     * 生成或更新映射文件
     */
    public async generateOrUpdateMapping(): Promise<boolean> {
        try {
            // 提取所有中文键名
            const chineseKeys = await this.extractChineseKeysFromWorkspace();

            if (chineseKeys.length === 0) {
                vscode.window.showInformationMessage(
                    "No Chinese keys found in workspace"
                );
                return false;
            }

            // 加载现有映射
            let existingMapping: KeyMapping = {};
            if (fs.existsSync(this.mappingFilePath)) {
                const content = fs.readFileSync(this.mappingFilePath, "utf-8");
                existingMapping = JSON.parse(content);
            }

            // 合并现有映射和新发现的键名
            const newMapping: KeyMapping = { ...existingMapping };
            let addedCount = 0;

            for (const chineseKey of chineseKeys) {
                const keyWithBrackets = `${chineseKey}`;
                if (!(keyWithBrackets in newMapping)) {
                    // 为新键生成默认值（可以自定义规则）
                    const defaultValue = this.generateDefaultValue(chineseKey);
                    newMapping[keyWithBrackets] = "";
                    addedCount++;
                }
            }

            // 更新内部映射
            this.keyMapping = newMapping;

            // 保存到文件
            const saved = await this.saveMapping();

            if (saved) {
                vscode.window.showInformationMessage(
                    `Mapping file updated. Found ${chineseKeys.length} Chinese keys, added ${addedCount} new mappings.`
                );
                return true;
            }

            return false;
        } catch (error) {
            vscode.window.showErrorMessage(
                `Error generating mapping: ${error}`
            );
            return false;
        }
    }

    /**
     * 根据中文生成默认英文值
     */
    private generateDefaultValue(chineseText: string): string {
        // 简单的中文到英文映射（可以根据需要扩展）
        const chineseToEnglish: { [key: string]: string } = {};

        // 检查是否有预定义映射
        for (const [chinese, english] of Object.entries(chineseToEnglish)) {
            if (chineseText.includes(chinese)) {
                return english;
            }
        }

        // 如果没有预定义映射，使用拼音首字母或其他策略
        // 这里简单返回原文的小写形式（去除空格）
        return chineseText.toLowerCase().replace(/\s+/g, "");
    }

    /**
     * 替换单个文件中的key
     */
    public async replaceInFile(
        document: vscode.TextDocument
    ): Promise<boolean> {
        // 排除映射文件本身
        const mappingFileName = path.basename(this.mappingFilePath);
        if (path.basename(document.fileName) === mappingFileName) {
            console.log(`Skipping mapping file: ${document.fileName}`);
            return false;
        }
        try {
            let content = document.getText();
            let modified = false;

            for (const [oldKey, newKey] of Object.entries(this.keyMapping)) {
                const escapedOldKey = oldKey.replace(
                    /[.*+?^${}()|[\]\\]/g,
                    "\\$&"
                );

                // 匹配 detail['[用户]'] 这样的模式
                const patterns = [
                    // obj['[用户]'] -> obj['user']
                    new RegExp(`(\\w+)\\[(['"])${escapedOldKey}\\2\\]`, "g"),
                    // ['[用户]'] -> ['user']
                    new RegExp(`(\\[(['"])${escapedOldKey}\\2\\])`, "g"),
                    // "[用户]" (独立字符串) -> "user"
                    new RegExp(
                        `(?<!\\w\\s*\\[\\s*)["']${escapedOldKey}["'](?![\\s\\]])`,
                        "g"
                    ),
                ];

                for (const pattern of patterns) {
                    if (pattern.test(content)) {
                        pattern.lastIndex = 0;

                        if (pattern.source.includes(`(\\w+)\\[(['"])`)) {
                            content = content.replace(
                                pattern,
                                `$1["${newKey}"]`
                            );
                        } else if (pattern.source.includes(`(\\[(['"])`)) {
                            content = content.replace(pattern, `["${newKey}"]`);
                        } else {
                            content = content.replace(pattern, `"${newKey}"`);
                        }
                        modified = true;
                    }
                }
            }

            if (modified) {
                const edit = new vscode.WorkspaceEdit();
                const fullRange = new vscode.Range(
                    document.positionAt(0),
                    document.positionAt(content.length)
                );
                edit.replace(document.uri, fullRange, content);
                await vscode.workspace.applyEdit(edit);
                return true;
            }

            return false;
        } catch (error) {
            vscode.window.showErrorMessage(
                `Error replacing keys in file: ${error}`
            );
            return false;
        }
    }

    /**
     * 替换单个文件并保存
     */
    public async replaceAndSaveFile(
        document: vscode.TextDocument
    ): Promise<boolean> {
        // 首先执行替换
        const modified = await this.replaceInFile(document);

        if (modified) {
            try {
                // 保存文件
                const saved = await document.save();
                if (saved) {
                    console.log(`Saved file: ${document.fileName}`);
                    return true;
                } else {
                    console.log(`Failed to save file: ${document.fileName}`);
                    return false;
                }
            } catch (error) {
                vscode.window.showErrorMessage(
                    `Error saving file ${document.fileName}: ${error}`
                );
                return false;
            }
        }

        return modified;
    }

    /**
     * 批量替换工作区中的文件并保存（排除映射文件）
     */
    public async replaceAndSaveInWorkspace(): Promise<{
        processed: number;
        modified: number;
        saved: number;
    }> {
        const config = vscode.workspace.getConfiguration("keyReplacer");
        const fileExtensions: string[] = config.get("fileExtensions", [
            ".ts",
            ".js",
            ".vue",
            ".json",
        ]);

        if (!vscode.workspace.workspaceFolders) {
            vscode.window.showErrorMessage("No workspace folder open");
            return { processed: 0, modified: 0, saved: 0 };
        }

        const workspaceFolder = vscode.workspace.workspaceFolders[0];
        const files = await this.findFiles(workspaceFolder.uri, fileExtensions);

        // 排除映射文件本身
        const mappingFileName = path.basename(this.mappingFilePath);
        const filteredFiles = files.filter((file) => {
            return path.basename(file.fsPath) !== mappingFileName;
        });

        console.log(
            `Found ${files.length} files, processing ${filteredFiles.length} files (excluding ${mappingFileName})`
        );

        let processedCount = 0;
        let modifiedCount = 0;
        let savedCount = 0;

        const progressOptions: vscode.ProgressOptions = {
            location: vscode.ProgressLocation.Notification,
            title: "Replacing and saving keys in files",
            cancellable: true,
        };

        await vscode.window.withProgress(
            progressOptions,
            async (progress, token) => {
                for (let i = 0; i < filteredFiles.length; i++) {
                    if (token.isCancellationRequested) {
                        break;
                    }

                    progress.report({
                        message: `Processing ${path.basename(
                            filteredFiles[i].fsPath
                        )} (${i + 1}/${filteredFiles.length})`,
                        increment: 100 / filteredFiles.length,
                    });

                    try {
                        processedCount++;
                        const document =
                            await vscode.workspace.openTextDocument(
                                filteredFiles[i]
                            );
                        const modified = await this.replaceInFile(document);

                        if (modified) {
                            modifiedCount++;
                            // 保存文件
                            const saved = await document.save();
                            if (saved) {
                                savedCount++;
                                console.log(
                                    `Saved modified file: ${document.fileName}`
                                );
                            }
                        }
                    } catch (error) {
                        console.error(
                            `Error processing ${filteredFiles[i].fsPath}:`,
                            error
                        );
                    }
                }
            }
        );

        return {
            processed: processedCount,
            modified: modifiedCount,
            saved: savedCount,
        };
    }

    /**
     * 查找工作区中的文件（排除映射文件）
     */
    private async findFiles(
        folder: vscode.Uri,
        extensions: string[]
    ): Promise<vscode.Uri[]> {
        // 构建排除模式，排除映射文件
        const config = vscode.workspace.getConfiguration("keyReplacer");
        const mappingFileName: string = config.get(
            "mappingFileName",
            "key-mapping.json"
        );

        // 构建文件搜索模式
        const includePattern = `**/*.{${extensions
            .map((ext) => ext.substring(1))
            .join(",")}}`;
        const excludePattern = `**/{node_modules,${mappingFileName}}/**`;

        const fileUris = await vscode.workspace.findFiles(
            includePattern,
            excludePattern
        );

        // 额外过滤，确保排除映射文件
        return fileUris.filter((uri) => {
            const fileName = path.basename(uri.fsPath);
            return (
                fileName !== mappingFileName &&
                extensions.includes(path.extname(uri.fsPath).toLowerCase())
            );
        });
    }
}
